# https://zhuanlan.zhihu.com/p/75872830?from_voters_page=true 函数作用
# 未完成：有人退出时clientsocket列表中无法空出位置，也不能更新玩家个数
# 视野模块 击杀消息显示
from socket import *
from tkinter import *
from _thread import *
from queue import Queue
from random import *
import time
from os import *

#变量定义
P=8 #最大玩家数
m=10
n=10 #地图行/列
denofcastle=9
denofmount=9
denofswamp=0
numofpls=0 #已连接玩家数
sta=0
numofdieplayer=0
turn=0
N=100 #最多操作数
M=5 #大本营间最近曼哈顿距离 待改
color=['grey','red','blue','green','yellow','purple','pink','cyan','orange']

#地图定义
class Block:
    def __init__(self,ty):
        self.type=int(ty) #0地 1山 2塔 3大本营 4沼泽
        self.army=0
        self.color=0
        if self.type==2:
            self.army=choice(range(40,50))
        self.lazytag=True  

#玩家定义
player=[0]
class Players:
    def __init__(self,nn):#第n个玩家
        self.die=False
        self.color=nn
        self.army=0
        self.land=1
        self.castle=1
        self.operate=Queue(maxsize=N)
        con=1
        while con:
            x = choice(range(1,n+1))
            y = choice(range(1,m+1))
            if(map[x][y].type!=0):continue
            for i in range(1, nn - 1 + 1):
                xa=player[i].home[0]
                ya=player[i].home[1]
                if (abs(xa - x) + abs(ya - y) <= M):
                    break
            else:
                con=0
                self.home=(x,y)
                self.highlight = [x,y]
                map[x][y].type=3
                map[x][y].color=nn
                map[x][y].army=1
       # self.p=Pen()
       # self.p.up()
       # self.p.shape('pictures\\highlight.gif')
       # self.p.pensize(800/min(m,n))
       # self.p.goto(800/min(m,n)*self.highlight[1]-400-400/min(m,n),-800/min(m,n)*self.highlight[0]+400+400/min(m,n))
    def kill(self,p):# 俘获玩家p (函数名改成capture?)
        # 修改player.army,land!!
        global numofdieplayer
        map[player[p].home[0]][player[p].home[1]].type=2
        for i in range(1,n+1):
            for j in range(1,m+1):
                if(map[i][j].color==p):
                    map[i][j].color=self.color
                    map[i][j].army=(map[i][j].army+1)//2
                   # map[i][j].lazytag=True
        player[p].die=True
        numofdieplayer+=1

#操作定义
class Act:
    def __init__(self,fx,fy,tx,ty,num):
        self.fx=fx
        self.fy=fy
        self.tx=tx
        self.ty=ty
        self.num=num
def movecom(s,t,mover):#此处进行了修改,wasd改为movecom,增加参数mover 
    global por1
    x=player[mover].highlight[0]
    y=player[mover].highlight[1]
    if not (x+s in range(1,n+1) and y+t in range(1,m+1)): return
    if r1: 
        player[1].operate.put(Act(player[1].highlight[0],player[1].highlight[1],player[1].highlight[0]+s,player[1].highlight[1]+t,por1),False)
    player[1].highlight=[x+s,y+t]
    por1=1
    # player[1].p.goto(800/min(m,n)*player[1].highlight[1]-400-400/min(m,n),-800/min(m,n)*player[1].highlight[0]+400+400/min(m,n))
    update()
    # palyer[1].p.stamp()
    
#网络连接
serversocket = socket(AF_INET,SOCK_STREAM)
host = gethostname()
port = 12345
serversocket.bind((host,port))
serversocket.listen(P)

csocket = socket(AF_INET,SOCK_STREAM)
clientsocket = [csocket]
addr = [0]

def connecter():
    global numofpls
    while sta==0:
        csocket,ad = serversocket.accept()
        clientsocket.append(csocket)
        addr.append(ad)
        numofpls+=1
        welcome="Connect Successfully!Please wait for other players."
        clientsocket[numofpls].send(welcome.encode("utf-8"))
        msg=clientsocket[numofpls].recv(1024)
        curpls.configure(text="There's " + str(numofpls) +" players are ready.")
        print(msg.decode("utf-8"))
        
start_new_thread(connecter,())

#编码传输
def sendd():
    return

#控件设置
def start(): # 这里写主程序
    if numofpls<2: return
    n = int(spinn.get())
    m = int(spinm.get())
    denofcastle = int(spincastle.get())
    denofmount = int(spinmount.get())
    denofswamp = int(spinswamp.get())
    sta = 1
    window.destroy()
    system("start /wait Generals_map_init.exe < g.in > g.out")
    map=[0]
    for i in range(1,n+1):
        map.append([0])
        inp=input().split()
        print(inp)
        for j in range(1,m+1):
            map[i].append(Block(inp[j-1]))
    for i in range(1,numofpls+1):
        player.append(Player(i))
    print("Go!")
   # 主进程
    global turn
    while numofdieplayer<numofpls-1:
        turn+=1
        for rsx in range(2):
            sendd()
            time.sleep(0.5)
            for mover in range(1,numofpls+1):
                if player[mover].die: continue
                if player[mover].operate.empty(): continue
                move=player[mover].operate.get(False)
                if map[move.tx][move.ty].type==1: continue#
                if map[move.fx][move.fy].color!=mover: continue#
                movenum=int(move.num*map[move.fx][move.fy].army)
                if movenum==map[move.fx][move.fy].army: movenum-=1
                if movenum==0: continue#
                map[move.fx][move.fy].lazytag=True
                map[move.tx][move.ty].lazytag=True
                map[move.fx][move.fy].army-=movenum
                if (map[move.tx][move.ty].type==0 or map[move.tx][move.ty].type==4):        # 平地or沼泽
                    if map[move.tx][move.ty].color==0:                                          #无归属
                        map[move.tx][move.ty].army+=movenum
                        map[move.tx][move.ty].color=player[mover].color
                        player[mover].land+=1
                    elif map[move.tx][move.ty].color==player[mover].color:                      #己方
                        map[move.tx][move.ty].army+=movenum
                    else:                                                                       #敌方
                        if movenum>map[move.tx][move.ty].army:                                      #占领
                            map[move.tx][move.ty].army=movenum-map[move.tx][move.ty].army
                            player[mover].army-=movenum-map[move.tx][move.ty].army
                            player[mover].land+=1
                            player[map[move.tx][move.ty].color].army-=movenum-map[move.tx][move.ty].army
                            player[map[move.tx][move.ty].color].land-=1
                            map[move.tx][move.ty].color=player[mover].color
                        else:                                                                       #未占领
                            map[move.tx][move.ty].army-=movenum
                            player[mover].army-=movenum
                            player[map[move.tx][move.ty].color].army-=movenum
                            
                else:                                                                       # 塔or大本营
                    if map[move.tx][move.ty].color==0:                                          #无归属
                        if movenum>map[move.tx][move.ty].army:                                      #占领
                            map[move.tx][move.ty].army=movenum-map[move.tx][move.ty].army
                            map[move.tx][move.ty].color=player[mover].color
                            player[mover].army-=movenum-map[move.tx][move.ty].army
                            player[mover].land+=1
                            player[mover].castle+=1
                        else:                                                                       #未占领
                            map[move.tx][move.ty].army-=movenum
                            player[mover].army-=movenum
                    elif map[move.tx][move.ty].color==player[mover].color:                      #己方
                        map[move.tx][move.ty].army+=movenum
                    else:                                                                       #敌方
                        if movenum>map[move.tx][move.ty].army:                                      #占领
                            player[mover].army-=movenum-map[move.tx][move.ty].army
                            player[mover].land+=1
                            player[mover].castle+=1
                            player[map[move.tx][move.ty].color].army-=movenum-map[move.tx][move.ty].army
                            player[map[move.tx][move.ty].color].land-=1
                            player[map[move.tx][move.ty].color].castle-=1
                            if(map[move.tx][move.ty].type==3): player[mover].kill(map[move.tx][move.ty].color) #占领大本营则消灭敌人
                            map[move.tx][move.ty].army=movenum-map[move.tx][move.ty].army
                            map[move.tx][move.ty].color=player[mover].color

                        else:                                                                       #未占领
                            map[move.tx][move.ty].army-=movenum
                            player[mover].army-=movenum
                            player[map[move.tx][move.ty].color].army-=movenum
        #更新士兵数目
        for i in range(1,n+1):
            for j in range(1,m+1):
                if (map[i][j].color!=0 and (map[i][j].type==2 or map[i][j].type==3)):
                    map[i][j].army+=1
                    player[map[i][j].color].army+=1
                    map[i][j].lazytag=True
                if (turn%25==0 and map[i][j].color!=0):
                    map[i][j].army+=1
                    player[map[i][j].color].army+=1
                    map[i][j].lazytag=True
                if (map[i][j].type==4 and map[i][j].army!=0):
                    map[i][j].army-=1
                    player[map[i][j].color].army-=1
                    if map[i][j].army==0:
                        player[map[i][j].color].land-=1
                        map[i][j].color=0
                    map[i][j].lazytag=True
    gameover()

window = Tk() # 建立窗口
window.title("Generals_Server")
notice = Label(window,text="Please reset the map if you want.") 
curpls = Label(window,text=str(numofpls) +" player(s) ready.")
hst = Label(window,text="Your hostname is " + str(host) +" .")
go = Button(window,text="Go!",command=start)
labn = Label(window,text="height")
labm = Label(window,text="width")
labcastle = Label(window,text="castle density")
labmount = Label(window,text="mount density")
labswamp = Label(window,text="swamp density")
labcent1 = Label(window,text="%")
labcent2 = Label(window,text="%")
labcent3 = Label(window,text="%")
n_state = IntVar()
m_state = IntVar()
castle_state = IntVar()
mount_state = IntVar()
swamp_state = IntVar()
n_state.set(n)
m_state.set(m)
castle_state.set(denofcastle)
mount_state.set(denofmount)
swamp_state.set(denofswamp)
spinn = Spinbox(window,from_=10,to=50,textvariable=n_state)
spinm = Spinbox(window,from_=10,to=50,textvariable=m_state)
spincastle = Spinbox(window,from_=0,to=18,textvariable=castle_state)
spinmount = Spinbox(window,from_=0,to=18,textvariable=mount_state)
spinswamp = Spinbox(window,from_=0,to=18,textvariable=swamp_state)

#控件安放
notice.grid(column=1,row=1)
hst.grid(column=1,row=2)
curpls.grid(column=1,row=3)
labn.grid(column=1,row=4)
spinn.grid(column=2,row=4)
labm.grid(column=1,row=5)
spinm.grid(column=2,row=5)
labcastle.grid(column=1,row=6)
spincastle.grid(column=2,row=6)
labcent1.grid(column=3,row=6)
labmount.grid(column=1,row=7)
spinmount.grid(column=2,row=7)
labcent2.grid(column=3,row=7)
labswamp.grid(column=1,row=8)
spinswamp.grid(column=2,row=8)
labcent3.grid(column=3,row=8)
go.grid(column=1,row=9)
go.focus()
window.mainloop()

